<?php
/**
 * Created by PhpStorm.
 * User: krystal
 * Date: 2019/6/17
 * Time: 11:49
 */

namespace app\api\controller\v9;


use app\api\controller\v2\Auth;
use app\common\lib\exception\ApiException;
use app\common\lib\Orders;
use app\common\lib\PayCheckSign;
use app\common\model\ZhunlePhysicalStoreOrder;
use app\common\pay\Weixin;
use think\Env;
use app\common\pay\Ali;

class PhysicalStore extends Auth
{
    public function _initialize()
    {
        parent::_initialize();
        if (!$this->is_apple_pay)
        {
            return show(config('code.error'), '服务异常');
        }
    }

    /**
     * 实体商品详情接口
     * @return \think\response\Json
     */
   public function goods_detail()
   {
       $param = request()->only('id');
       $validate = validate('PhysicalStore');
       if ($validate->scene('goods_detail')->check($param) !== true)
       {
           return show(config('code.error'),$validate->getError());
       }
       // m站地址host
       $host = Env::get('host.domain') .'/goods_detail?id=';
       $goods = config('physical_store_goods');
       $arr =[];
       foreach ($goods as $good)
       {
           if ($good['id'] == $param['id'])
           {
               $arr=[
                   'url'=>$host.$param['id'],
                   'name'=>$good['name'],
                   'des'=>$good['des'],
                   'icon'=>$img = $good['icon'],
                   'or_price'=>$good['or_price'],
                   'now_price'=>$good['now_price']
               ];
           }
       }

       return show(config('code.success'),'获取数据成功',$arr);
   }

    /**
     * 实体商品下单接口
     * @return array|bool
     * @throws ApiException
     * @throws \Exception
     */
    public function pay_order()
   {
       $param = request()->only('trade_type,openid,gid,real_name,telphone,address,num');
       $param['remark'] = input('param.remark','');
       $openid = input('param.openid','');

       $validate = validate('PhysicalStore');
       if ($validate->scene('pay_order')->check($param) !== true)
       {
           return show(config('code.error'),$validate->getError());
       }
       // 生成唯一订单号  011806192149570386 01蜡烛
       $out_trade_no = str_pad(1, 2, '0', STR_PAD_LEFT) . date('YmdHis') . str_pad(random_int(1, 9999), 4, '0', STR_PAD_LEFT);

       //获取商品信息
       $goods = config('physical_store_goods');
       $gname = '商品';
       $price = 0;
       foreach ($goods as $good)
       {
           if ($param['gid'] == $good['id'])
           {
               $gname = $good['name'];
               $price = $good['now_price'] * $param['num'];
           }
       }
       /**
        * $account int 下单使用的商户配置id
        * 支付方式   1=>支付宝，2=>微信支付，5=>京东支付，6=>微信公众号支付，7=>支付宝手机网页支付，8=>微信H5网页支付
        */
       switch ($param['trade_type'])
       {
           case 1:
               $account = (int)config('alipay.default');
               break;
           case 2:
               $account = (int)config('wxpay.default');
               break;
           case 5:
               $account = (int)config('jdpay.default');
               break;
           case 6:
               $account = (int)config('wxpay.default');
               break;
           case 7:
               $account = (int)config('alipay.default');
               break;
           case 8:
               $account = (int)config('wxpay.default');
               break;
           default:
               $account = 1;
               break;
       }

       $insert = [
           'order_type' => 1,
           'order_status' => 0,
           'uid' => $this->user['id'],
           'gid' => $param['gid'],
           'gnum' => $param['num'],
           'order_id' => $out_trade_no,
           'trade_type' => $param['trade_type'],
           'total_amount' => $price,
           'account'=>$account,
           'create_time' => time(),
           'extend' => json_encode(['real_name'=>$param['real_name'],'telphone'=>$param['telphone'],'remark'=>$param['remark'],'address'=>$param['address']],true)
       ];

       $OrderModel = new ZhunlePhysicalStoreOrder();
       // 生成订单到数据库
       try
       {
           $oid = $OrderModel->insertGetId($insert);
       }
       catch (\Exception $e)
       {
           \think\Log::write($e->getMessage(), 'error');
           throw new ApiException('下单失败,请重新操作');
       }
       //支付订单
       $arr = (new Orders())->unifyPayOrder([
           'oid'=>$oid,
           'trade_type' => $param['trade_type'],
           'total_amount' => $price,
           'pay_des' => '准了 - '.$gname,
           'order_id' => $out_trade_no,
           'openid' => $openid,
           'callback_url' => '',
           'order_type' => 1
       ],2);

       $arr['data']['skuId'] = 'apple_pay_' . $param['gid'];

       return show(config('code.success'),'下单成功',$arr['data']);
   }

    /**
     * 订单重新支付
     * @return \think\response\Json
     * @throws \app\common\lib\exception\ApiException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \Exception
     */
    public function pay_again()
    {
        if (!request()->isPost())
        {
            return show(config('code.error'), '未知操作', [], 403);
        }

        $param = request()->param();

        $openid = input('param.openid', '');// openid

        $callback_url = $param['callback_url'] ?? '';

        $validate = validate('PhysicalStore');
        if ($validate->scene('order')->check($param) !== true)
        {
            return show(config('code.error'),$validate->getError());
        }

        $OrdersModel = new ZhunlePhysicalStoreOrder();
        $OrdersLib = new Orders();
        //检测当前订单是否存在
        $orders = $OrdersModel->OrderDetail($param);

        //支付客户端判断该订单是否已经支付,若已经支付,但是status=0;就更改status=1
        $validateResult = $this->validate_orders(['orders' => $orders]);

        if($validateResult !== true)
        {
            return show(config('code.error'),$validateResult);
        }

        if ($orders)
        {
            //获取商品信息
            $goods = config('physical_store_goods');
            $pay_des = '准了 - 商品';
            foreach ($goods as $good)
            {
                if ($orders['gid'] == $good['id'])
                {
                    $pay_des = '准了 - '.$good['name'];
                }
            }

            /**
             * $account int 下单使用的商户配置id
             * 支付方式   1=>支付宝，2=>微信支付，5=>京东支付，6=>微信公众号支付，7=>支付宝手机网页支付，8=>微信H5网页支付
             */
            switch ($param['trade_type'])
            {
                case 1:
                    $account = (int)config('alipay.default');
                    break;
                case 2:
                    $account = (int)config('wxpay.default');
                    break;
                case 5:
                    $account = (int)config('jdpay.default');
                    break;
                case 6:
                    $account = (int)config('wxpay.default');
                    break;
                case 7:
                    $account = (int)config('alipay.default');
                    break;
                case 8:
                    $account = (int)config('wxpay.default');
                    break;
                default:
                    $account = 1;
                    break;
            }

            /**
             * 更新支付方式 和 当前使用的支付配置
             */
            try
            {
                $OrdersModel->where(['id' => $param['oid']])->update(['trade_type' => $param['trade_type'], 'account' => $account]);
            }
            catch (\Exception $e)
            {
                return show(config('code.error'), $e->getMessage(), [], 500);
            }

            //支付订单
            $data = $OrdersLib->unifyPayOrder(['oid'=>$orders['id'],'order_type' => 1, 'trade_type' => $param['trade_type'], 'total_amount' => $orders['total_amount'], 'pay_des' => $pay_des, 'order_id' => $orders['order_id'], 'openid' => $openid, 'callback_url' => $callback_url],2);

            $data['data']['skuId'] = $orders['gid'];

            return show(config('code.success'), '下单成功', $data['data']);
        }

        return show(config('code.error'), '当前订单不存在');
    }


    /**
     * 验证订单是否已经支付
     * @param array $map
     * @return bool|string
     * @throws ApiException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private function validate_orders($map = [])
    {
        $orders = $map['orders'];

        if(!empty($orders))
        {
            // 若该订单已支付，则直接返回已支付
            if ($orders['order_status'] > 0)
            {
                if ($orders['trade_type'] == 1)
                {
                    return '订单已在支付宝支付';
                } elseif ($orders['trade_type'] == 2)
                {
                    return '订单已在微信支付';
                } else
                {
                    return '订单已支付';
                }
            }

            $orderAccount = isset($orders['account']) ? (int)($orders['account']) : 1;

            // 订单支付方式为支付宝
            if ($orders['trade_type'] == 1)
            {
                $ali = new Ali();

                $response = json_decode(json_encode($ali->query(['out_trade_no' => $orders['order_id']], $orderAccount)), true);

                // 支付宝已经内置验签 支付成功
                if ($response['alipay_trade_query_response']['code'] == '10000')
                {
                    $tarde_status = $response['alipay_trade_query_response']['trade_status'];

                    if ($tarde_status == 'TRADE_SUCCESS')
                    {
                        return '订单已在支付宝支付';
                    }
                }
            } // 订单支付方式为微信支付
            elseif (in_array($orders['trade_type'], [2, 6, 8]))
            {
                $weixin = new Weixin();
                $wxpayConfig = self::getPayConfig('wx', $orderAccount);

                if (empty($wxpayConfig))
                {
                    return '操作失败,请稍后重试';
                }

                $wxPayType = $wxpayConfig['wx_pay_type'][$orders['trade_type']];
                // 获取微信配置信息
                $wxConfig = $wxpayConfig[$wxPayType['configName']];

                $response = $weixin->query($orders['order_id'], $wxConfig);
                // 验签
                if ((new PayCheckSign())->weixin($response, $wxConfig['api_key']))
                {
                    if ($response['return_code'] === 'SUCCESS')
                    {
                        if ($response['result_code'] === 'SUCCESS' && $response['trade_state'] == 'SUCCESS')
                        {
                            return '订单已在微信支付';
                        }
                    } else
                    {
                        return '网络异常';
                    }
                } else
                {
                    return '网络异常';
                }
            }
            //订单关闭

            if ($orders['order_status'] == 2)
            {
                return '订单已关闭';
            }
        }

        return true;
    }

    /**
     * 获取支付参数
     * 未获取到相关配置时，返回空数组
     * @param string $type 支付类型 ali=>支付宝 wx=>微信支付 jd=>京东支付
     * @param int $account 需要强制获取非使用中的配置，目前主要用于进行订单查询 （下单时不需要传参）
     * @return array
     */
    public static function getPayConfig($type = 'ali', $account = 0)
    {
        $type = strtolower($type) . 'pay';

        $config = config($type);

        if (empty($config))
        {
            return [];
        }

        if ($account > 0 && isset($config['account' . $account]))
        {
            $data = $config['account' . $account];
        } else
        {
            $data = $config['account' . $config['default']];
        }

        return $data;
    }

    /**
     * 实体商品订单列表接口
     * @return \think\response\Json
     */
   public function orders()
   {

       if ($this->headers['app-type'] == 'ios')
       {
           $type = input('param.type',0);
           $page = input('param.page',1);
           $orderModel = new ZhunlePhysicalStoreOrder();
           $orders = $orderModel->UserOrder(['uid'=>$this->user['id'],'type'=>$type,'page'=>$page]);
           $goods = config('physical_store_goods');
           $arr=[];
           $gname = '';
           $gdes = '';
           $icon = '';
           $or_price = '';
           $now_price = '';
           if (isset($orders['data']) && $orders['data'])
           {
               foreach ($orders['data'] as $order)
               {
                   foreach ($goods as $good)
                   {
                       if ($order['gid'] == $good['id'])
                       {
                           $gname = $good['name'];
                           $gdes = $good['des'];
                           $icon = $good['icon'];
                           $or_price = $good['now_price'];
                           $now_price = $good['now_price'];
                       }
                   }
                   $arr[]= [
                       'oid'=>$order['id'],
                       'total_price'=>$order['total_amount'],
                       'create_time'=>date('Y-m-d H:i:s',$order['create_time']),
                       'order_id'=>$order['order_id'],
                       'order_status'=>$order['order_status'],
                       'trade_type'=>$order['trade_type'],
                       'gnum'=>$order['gnum'],
                       'express_number'=>$order['express_number'],
                       'type'=>1,
                       'physical_store_data'=>[
                           'gid'=>$order['gid'],
                           'name'=>$gname,
                           'des'=>$gdes,
                           'icon'=>$icon,
                           'or_price'=>$or_price,
                           'now_price'=>$now_price
                       ]
                   ];
               }
               $orders['data'] = $arr;
           }
           return show(config('code.success'),'获取成功',$orders);
       }

       return show(config('code.error'), '服务异常');

   }

    /**
     * 实体商品订单详情接口
     * @return \think\response\Json
     */
   public function order()
   {
       $param = request()->only('oid');

       $validate = validate('PhysicalStore');
       if ($validate->scene('order')->check($param) !== true)
       {
           return show(config('code.error'),$validate->getError());
       }

       $orderModel = new ZhunlePhysicalStoreOrder();
       $order = $orderModel->OrderDetail($param);
       if ($order)
       {

           $gname = '';
           $gdes = '';
           $or_price = '';
           $now_price = '';
           $goods = config('physical_store_goods');
           foreach ($goods as $good)
           {
               if ($order['gid'] == $good['id'])
               {
                   $gname = $good['name'];
                   $gdes = $good['des'];
                   $or_price = $good['now_price'];
                   $now_price = $good['now_price'];
               }
           }
           $receive_info = json_decode($order['extend'],true);
           $arr =[
               'status'=>$order['order_status'],
               'data'=>[
                   0=>[
                       'gid'=>$order['gid'],
                       'name'=>$gname,
                       'des'=>$gdes,
                       'or_price'=>$or_price,
                       'now_price'=>$now_price
                   ]
               ],
               'gnum'=>$order['gnum'],
               'or_total_price'=>sprintf('%.2f',$or_price * $order['gnum']),
               'total_price'=>$order['total_amount'],
               'trade_type'=>$order['trade_type'],
               'order_id'=>$order['order_id'],
               'express_number'=>$order['express_number'],
               'order_time'=>[
                   0=>[
                       'name'=>'订单创建时间',
                       'value'=>date('Y-m-d H:i:s',$order['create_time']),
                   ]
               ],
               'receive_info'=>[
                   'real_name'=>$receive_info['real_name'],
                   'telphone'=>$receive_info['telphone'],
                   'remark'=>$receive_info['remark'],
                   'address'=>$receive_info['address']
               ]
           ];
           return show(config('code.success'),'获取成功',$arr);
       }
       return show(config('code.error'),'订单不存在');
   }

   public function del_order()
   {
       $param = request()->only('oid');

       $validate = validate('PhysicalStore');
       if ($validate->scene('order')->check($param) !== true)
       {
           return show(config('code.error'),$validate->getError());
       }

       $OrdersModel = new ZhunlePhysicalStoreOrder();

       $order = $OrdersModel->OrderDetail($param);
       if ($order)
       {
           if (!$order['del_time'])
           {
               $res = $OrdersModel->DelOrder($param);
               if ($res)
               {
                   return show(config('code.success'),'删除成功');
               }

               return show(config('code.error'),'删除失败');
           }

           return show(config('code.success'),'订单已删除');
       }
       return show(config('code.success'),'订单不存在');
   }
}
